/*
 * (C) 2009, Elephant Seven Hamburg Gmbh, 
 * Author: Detlev Wiese
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
 * use this file except in compliance with the License. You may obtain a copy 
 * of the License at
 *  
 *     http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.se and its accompanying notice file is
 * included with the distribution. 
 */ 
package com.e7.streams;

/**
 * A stream class which maps all elements of itself to another 
 * stream using a {@code MappingFunction}-object.  
 * @param <F> The type of the mapping function
 * @param <E> The type of the underlying stream given 
 * @see MappingFunction
 */
public class MappedStream<F, E> extends AbstractStream<F> 
	implements Stream<F> 
{
	private MappingFunction<F, E> function; 
	private Stream<E> stream; 
	
	/**
	 * Create an instance!
	 * @param function The function to be applied to all elements 
	 * of the stream
	 * @param stream The 'underlying' stream which carries objects 
	 * of the domain-range of the mapping function
	 */
	public MappedStream(
				MappingFunction<F,E> function, 
				Stream<E> stream) 
	{
		this.stream = stream; 
		this.function = function;  
	}
	
	/**
	 * Syntactic sugar only. 
	 * See {@link MappedStream#MappedStream(MappingFunction, Stream).
	 */
	public MappedStream(
			Stream<E> stream, 
			MappingFunction<F,E> function) 
	{
		this(function, stream); 
	}
	
	public boolean hasNext() {
		return stream.hasNext(); 
	}
	
	/**
	 * {@inheritDoc}
	 * <P>The receiver will apply its function and return the 
	 * result of the function call.</P>
	 */
	public F next() {
		return function.value(stream.next());
	}
}
